package org.learning;

import java.util.Random;
import java.util.concurrent.Semaphore;
import java.util.stream.IntStream;

/**
 * Semaphore的应用
 * 案例：大学生到自习室抢座，写作业
 */
public class A_21 {
    static class StudentThread extends Thread {
        private final Semaphore semaphore;
        private final Random random = new Random();

        public StudentThread(String name, Semaphore semaphore) {
            super(name);
            this.semaphore = semaphore;
        }

        @Override
        public void run() {
            try {
                //假设每个学生只占一个座位。如果占多个，可以方法里面传多个。
                semaphore.acquire();
                System.out.println(Thread.currentThread().getName() + "-抢座成功！开始写作业");
                //写作业最多写100秒
                Thread.sleep(random.nextInt(100000));
                System.out.println(Thread.currentThread().getName() + "-作业写完！离开座位");
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            //假设每个学生只占一个座位，那么作业写完离开座位也就会释放一个，如果占多个那么释放也释放多个。
            semaphore.release();
        }
    }

    public static void main(String[] args) {
        //自习室最多20个座位
        //自习室外未抢到座位的人，如果按照先来后到排队，即公平。
        //不按照先来后到排队，非公平。对应Semaphore构造参数的第二个，fair，默认非公平，因为效率更高。
        Semaphore semaphore = new Semaphore(20);
        //40个学生来抢座
        IntStream
                .rangeClosed(0, 40)
                .mapToObj(v -> new StudentThread("学生" + v, semaphore))
                .forEach(Thread::start);

    }
}
